@levels = ('Log', 'Trace','Debug','Info','Warn','Error','Fatal');
@clitypes = ('System.Boolean','System.Char','System.Byte','System.String','System.Int32','System.Int64','System.Single','System.Double','System.Decimal','System.Object');
@nonclstypes = ('System.SByte','System.UInt32','System.UInt64');

$loggercs = "../src/NLog/Logger.cs";

open(IN, "<$loggercs");
open(OUT, ">$loggercs.tmp");
while (<IN>)
{
    print OUT;
    last if (m/the following code has been automatically generated by a PERL/);
}

for $level (@levels) {

    if ($level eq "Log") {
        $level2 = "level";
        $level3 = "specified";
        $isenabled = "this.IsEnabled(level)";
        $arg0 = "LogLevel level, ";
        $param0 = qq!\n        /// <param name="level">The log level.</param>!;
    } else {
        $level2 = "LogLevel.$level";
        $level3 = "<c>$level</c>";
        $isenabled = "this.Is${level}Enabled";
        $arg0 = "";
        $param0 = "";
    }


    print OUT <<EOT;
        #region $level() overloads 

        /// <overloads>
        /// Writes the diagnostic message at the $level3 level using the specified format provider and format parameters.
        /// </overloads>
        /// <summary>
        /// Writes the diagnostic message at the $level3 level.
        /// </summary>
        /// <typeparam name="T">Type of the value.</typeparam>$param0
        /// <param name="value">The value to be written.</param>
        public void $level<T>(${arg0}T value)
        {
            if ($isenabled)
            {
                this.WriteToTargets($level2, null, value);
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level.
        /// </summary>
        /// <typeparam name="T">Type of the value.</typeparam>$param0
        /// <param name="formatProvider">An IFormatProvider that supplies culture-specific formatting information.</param>
        /// <param name="value">The value to be written.</param>
        public void $level<T>(${arg0}IFormatProvider formatProvider, T value)
        {
            if ($isenabled)
            {
                this.WriteToTargets($level2, formatProvider, value);
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level.
        /// </summary>$param0
        /// <param name="messageFunc">A function returning message to be written. Function is not evaluated if logging is not enabled.</param>
        public void $level(${arg0}LogMessageGenerator messageFunc)
        {
            if ($isenabled)
            {
                if (messageFunc == null)
                {
                    throw new ArgumentNullException("messageFunc");
                }

                this.WriteToTargets($level2, null, messageFunc());
            }
        }

        /// <summary>
        /// Writes the diagnostic message and exception at the $level3 level.
        /// </summary>$param0
        /// <param name="message">A <see langword="string" /> to be written.</param>
        /// <param name="exception">An exception to be logged.</param>
        public void ${level}Exception(${arg0}[Localizable(false)] string message, Exception exception)
        {
            if ($isenabled)
            {
                this.WriteToTargets($level2, message, exception);
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level using the specified parameters and formatting them with the supplied format provider.
        /// </summary>$param0
        /// <param name="formatProvider">An IFormatProvider that supplies culture-specific formatting information.</param>
        /// <param name="message">A <see langword="string" /> containing format items.</param>
        /// <param name="args">Arguments to format.</param>
        public void $level(${arg0}IFormatProvider formatProvider, [Localizable(false)] string message, params object[] args)
        { 
            if ($isenabled)
            {
                this.WriteToTargets($level2, formatProvider, message, args); 
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level.
        /// </summary>$param0
        /// <param name="message">Log message.</param>
        public void $level(${arg0}[Localizable(false)] string message) 
        { 
            if ($isenabled)
            {
                this.WriteToTargets($level2, null, message);
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level using the specified parameters.
        /// </summary>$param0
        /// <param name="message">A <see langword="string" /> containing format items.</param>
        /// <param name="args">Arguments to format.</param>
        public void $level(${arg0}[Localizable(false)] string message, params object[] args) 
        { 
            if ($isenabled)
            {
                this.WriteToTargets($level2, message, args);
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level using the specified parameter and formatting it with the supplied format provider.
        /// </summary>
        /// <typeparam name="TArgument">The type of the argument.</typeparam>$param0
        /// <param name="formatProvider">An IFormatProvider that supplies culture-specific formatting information.</param>
        /// <param name="message">A <see langword="string" /> containing one format item.</param>
        /// <param name="argument">The argument to format.</param>
        public void $level<TArgument>(${arg0}IFormatProvider formatProvider, [Localizable(false)] string message, TArgument argument)
        { 
            if ($isenabled)
            {
                this.WriteToTargets($level2, formatProvider, message, new object[] { argument }); 
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level using the specified parameter.
        /// </summary>
        /// <typeparam name="TArgument">The type of the argument.</typeparam>$param0
        /// <param name="message">A <see langword="string" /> containing one format item.</param>
        /// <param name="argument">The argument to format.</param>
        public void $level<TArgument>(${arg0}[Localizable(false)] string message, TArgument argument)
        { 
            if ($isenabled)
            {
                this.WriteToTargets($level2, message, new object[] { argument });
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level using the specified arguments formatting it with the supplied format provider.
        /// </summary>
        /// <typeparam name="TArgument1">The type of the first argument.</typeparam>
        /// <typeparam name="TArgument2">The type of the second argument.</typeparam>$param0
        /// <param name="formatProvider">An IFormatProvider that supplies culture-specific formatting information.</param>
        /// <param name="message">A <see langword="string" /> containing one format item.</param>
        /// <param name="argument1">The first argument to format.</param>
        /// <param name="argument2">The second argument to format.</param>
        public void $level<TArgument1, TArgument2>(${arg0}IFormatProvider formatProvider, [Localizable(false)] string message, TArgument1 argument1, TArgument2 argument2) 
        { 
            if ($isenabled)
            {
                this.WriteToTargets($level2, formatProvider, message, new object[] { argument1, argument2 }); 
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level using the specified parameters.
        /// </summary>
        /// <typeparam name="TArgument1">The type of the first argument.</typeparam>
        /// <typeparam name="TArgument2">The type of the second argument.</typeparam>$param0
        /// <param name="message">A <see langword="string" /> containing one format item.</param>
        /// <param name="argument1">The first argument to format.</param>
        /// <param name="argument2">The second argument to format.</param>
        public void $level<TArgument1, TArgument2>(${arg0}[Localizable(false)] string message, TArgument1 argument1, TArgument2 argument2)
        { 
            if ($isenabled)
            {
                this.WriteToTargets($level2, message, new object[] { argument1, argument2 });
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level using the specified arguments formatting it with the supplied format provider.
        /// </summary>
        /// <typeparam name="TArgument1">The type of the first argument.</typeparam>
        /// <typeparam name="TArgument2">The type of the second argument.</typeparam>
        /// <typeparam name="TArgument3">The type of the third argument.</typeparam>$param0
        /// <param name="formatProvider">An IFormatProvider that supplies culture-specific formatting information.</param>
        /// <param name="message">A <see langword="string" /> containing one format item.</param>
        /// <param name="argument1">The first argument to format.</param>
        /// <param name="argument2">The second argument to format.</param>
        /// <param name="argument3">The third argument to format.</param>
        public void $level<TArgument1, TArgument2, TArgument3>(${arg0}IFormatProvider formatProvider, [Localizable(false)] string message, TArgument1 argument1, TArgument2 argument2, TArgument3 argument3) 
        { 
            if ($isenabled)
            {
                this.WriteToTargets($level2, formatProvider, message, new object[] { argument1, argument2, argument3 }); 
            }
        }

        /// <summary>
        /// Writes the diagnostic message at the $level3 level using the specified parameters.
        /// </summary>
        /// <typeparam name="TArgument1">The type of the first argument.</typeparam>
        /// <typeparam name="TArgument2">The type of the second argument.</typeparam>
        /// <typeparam name="TArgument3">The type of the third argument.</typeparam>$param0
        /// <param name="message">A <see langword="string" /> containing one format item.</param>
        /// <param name="argument1">The first argument to format.</param>
        /// <param name="argument2">The second argument to format.</param>
        /// <param name="argument3">The third argument to format.</param>
        public void $level<TArgument1, TArgument2, TArgument3>(${arg0}[Localizable(false)] string message, TArgument1 argument1, TArgument2 argument2, TArgument3 argument3)
        { 
            if ($isenabled)
            {
                this.WriteToTargets($level2, message, new object[] { argument1, argument2, argument3 });
            }
        }

        #endregion

EOT


}

while (<IN>)
{
    if (m/end of generated code/)
    {
        print OUT;
        last;
    }
}

while (<IN>)
{
    print OUT;
}
close(OUT);
close(IN);
unlink($loggercs);
rename("$loggercs.tmp", "$loggercs");

